<?php

class Sgit_Model extends Zend_Db_Table_Abstract
{
    protected $_name = null;
    protected $_cache_activa = false;
    protected $_cache = null;
    protected $_profiler = true;


    function __construct($options = null)
    {
        $this->_cache = $this->_getCache();
        $options = array('metadataCache' => $this->_cache);
        $this->_logger = Zend_Registry::get('loggerTxt');
        $this->_idZona = Zend_Controller_Front::getInstance()->getRequest()->getParam('idZona');



        parent::__construct($options);

        $this->db=$this->getAdapter();
       // $this->alter();

    }
   
    /**
     *
     * Los metodos que hay aqui son genericos , tratan directamente sobre la tabla, sin hacer uso de Join
     *
     * Si necesitamos otro tipo de query se hace directamente en la clase Hija.
     * Los nombres son autoexplicativos
     *
     */


    public function getTableName()
    {
        return $this->_name;
    }


    public function where(&$select, $where = null)
    {

        if (is_numeric($where))
        {
            $select->where("id = ?", $where, 'INTEGER');
        } elseif (!is_null($where))
        {
            $this->_where($select, $where);
        }
    }


    public function where_action($where = null)
    {

        if (is_numeric($where))
        {
            $donde[] = $this->getAdapter()->quoteInto("id = ?", $where, 'INTEGER');
        } elseif (!is_null($where))
        {
            if (is_array($where))
            {
                foreach ($where as $k => $v)
                {
                    $donde[] = $this->getAdapter()->quoteInto($k, $v);
                }
            } else
            {
                $donde[] = $this->getAdapter()->quoteInto("id = ?", $where);
            }

        }

        return implode(' AND ', $donde);
    }


    public function getOne($col, $where = null)
    {
        if (!isset($col))
            throw new Zend_Db_Table_Exception('Faltan Parametros,getOne');

        $row = $this->getRow($where, $col);


        return $row[$col];
    }

    public function getRow($where = null, $values = null)
    {

        if (!isset($where))
            throw new Zend_Db_Table_Exception('Faltan Parametros,getRow');


        $select = $this->select();

        if (!is_null($values))
        {
            $select->from($this->_name, $values);
        }

        if (!is_null($where))
        {
            $this->where($select, $where);
        }


        $row = $this->fetchRow($select);


        if ($row instanceof Zend_Db_Table_Row)
        {
            return $row->toArray();
        } else
        {
            return $row;
        }

    }

    public function getCol($col, $where = null, $order = null, $group = null, $count = null, $offset = null, $id_zona = null)
    {
        if (!isset($col))
            throw new Zend_Db_Table_Exception('Faltan Parametros,getCol');


        $rows = $this->getAll($where, $order, $group, $count, $offset, $id_zona, $col);
        foreach ($rows as $v)
        {
            $salida[] = $v[$col];
        }
        return $salida;
    }

    public function getAssoc($key = 'id', $values = null, $where = null, $order = null, $group = null, $count = null, $offset = null, $id_zona = null)
    {
        //if($values)$values[]=$key;

        $rows = $this->getAll($where, $order, $group, $count, $offset, $id_zona);

        foreach ($rows as $v)
        {
            $k = $v[$key];

            if (!is_null($values))
            {
                if (is_array($values))
                {
                    foreach ($values as $c)
                    {
                        $salida[$k][$c] = $v[$c];
                    }
                } else
                {
                    $salida[$k] = $v[$values];
                }
            } else
            {
                $salida[$k] = $v;
            }

        }
        return $salida;
    }

    /**
     * 
     * Funciona como getAssoc salvo que la clave se puede repetir por tanto
     *  devuelve todos los calores para todas las claves
     * 
     */

    public function getAssocMultiple($key = 'id', $key2 = 'id', $values = null, $where = null, $order = null, $group = null, $count = null, $offset = null, $id_zona = null)
    {
        if (!is_null($values))
        {
            $values[] = $key;
            $values[] = $key2;

        }
        $rows = $this->getAll($where, $order, $group, $count, $offset, $id_zona, $values);


        foreach ($rows as $v)
        {
            $k = $v[$key];
            $n = $v['id'];
            if (!is_null($values))
            {
                if (is_array($values))
                {
                    foreach ($values as $g => $c)
                    {
                        $salida[$k][$n][$c] = $v[$c];
                    }
                } else
                {
                    $salida[$k][$n] = $v[$values];
                }
            } else
            {
                $salida[$k][$n] = $v;
            }


        }
        return $salida;
    }
    
    public function assocArray($rows, $key = 'id', $values = null)
    {


        foreach ((array )$rows as $v)
        {
            $k = $v[$key];

            if (!is_null($values))
            {
                $salida[$k][] = $v[$values];
            } else
            {
                $salida[$k][] = $v;
            }

        }


        return $salida;
    }
    public function assocArray2($rows, $key = 'id', $values = null)
    {


        foreach ((array )$rows as $v)
        {
            $k = $v[$key];

            if (!is_null($values))
            {
                $salida[$k] = $v[$values];
            } else
            {
                $salida[$k] = $v;
            }

        }


        return $salida;
    }

    public function getColByZona($id_zona, $col, $where = null, $order = null, $group = null, $count = null, $offset = null)
    {
        if (!$id_zona || !$col)
            throw new Zend_Db_Table_Exception('Faltan Parametros,getColByZona');

        return $this->getCol($col, $where, $order, $group, $count, $offset, $id_zona);
    }

    public function getAssocByZona($id_zona, $key = 'id', $values = null, $where = null, $order = null, $group = null, $count = null, $offset = null)
    {
        if (!$id_zona)
            throw new Zend_Db_Table_Exception('Faltan Parametros,getAssocByZona');

        return $this->getAssoc($key, $values, $where, $order, $group, $count, $offset, $id_zona);
    }

    public function getAllByZona($id_zona, $where = null, $order = null, $group = null, $count = null, $offset = null, $values = null)
    {
        if (!$id_zona)
            throw new Zend_Db_Table_Exception('Faltan Parametros,getAllByZona');

        return $this->getAll($where, $order, $group, $count, $offset, $id_zona, $values);
    }


    public function getAll($where = null, $order = null, $group = null, $count = null, $offset = null, $id_zona = null, $values = null)
    {

        $select = $this->select();

        if (!is_null($values))
        {
            $select->from($this->_name, $values);
        }


        if (!is_null($where))
        {
            $this->where($select, $where);
        }


        if (!is_null($id_zona))
        {
            $select->where("id_zona = ?", $id_zona, 'INTEGER');
        }
        if (!is_null($order))
        {
            $this->_order($select, $order);
        }
        if (!is_null($group))
        {
            $select->group($group);
        }
        if (!is_null($count) || !is_null($offset))
        {
            $select->limit($count, $offset);
        }

        $rowset = $this->fetchAll($select);


        if (($rowset instanceof Zend_Db_Table_Rowset))
        {
            return $rowset->toArray();
        } else
        {
            return $rowset;
        }


    }


    /**
     * 
     * 
     * Updates
     * 
     * 
     */

    public function updateRow($record = array(), $where)
    {

        $where = $this->where_action($where);

        if (empty($record['updated_on']))
        {
            $record['updated_on'] = new Zend_Db_Expr('NOW()');
        }

        if (empty($record['updated_by']))
        {
            $auth = Zend_Auth::getInstance();
            $record['updated_by'] = $auth->getIdentity()->id;
        }


        if (!$where)
            throw new Zend_Db_Table_Exception('Faltan Parametros,update');


        $this->update($record, $where);

        $this->_updateCache();
        return $id;
    }


    final public function insertRow($record = array())
    {
        if (empty($record))
        {
            throw new Zend_Db_Table_Exception('Faltan Parametros,insert');
        }


        if (empty($record['created_on']))
        {
            $record['created_on'] = new Zend_Db_Expr('NOW()');
        }
        if (empty($record['created_by']))
        {
            $auth = Zend_Auth::getInstance();
            $record['created_by'] = $auth->getIdentity()->id;
        }

        $id = $this->insert($record);

        $this->_updateCache();
        return $id;

    }

    /**
     * 
     * 
     * Delete
     * 
     * 
     * 
     */


    public function deleteRow($where)
    {
        if (!$where)
            throw new Zend_Db_Table_Exception('Faltan Parametros,delete');

        $where = $this->where_action($where);


        $n = $this->delete($where);
        $this->_updateCache();
        return $n;

    }


    /**
     * 
     *  Combos O Select
     * 
     * 
     * 
     * 
     * 
     */


    final public function formSelect($label,$name, $key = 'id', $col = 'nombre',$where = null,$notFirstBlank=false, $order = null, $group = null, $count = null, $offset = null, $id_zona = null)
    {
        $element =new  Zend_Form_Element_Select($name);
        $options = $this->getAssoc($key, $col, $where, $order, $group, $count, $offset, $id_zona);
        
        if($notFirstBlank!=true){
            Sgit_Util_FirstBlank::run($options);
        }

        $element->addFilter('Null');
        $element->setLabel($label);
        
        $value=Zend_Controller_Front::getInstance()->getRequest()->getParam($name,null);
        $element->setValue($value);
        
        $element->addMultiOptions($options);
        return $element;
    }

    final public function formSelectByZona($idZona,$label,$name, $key = 'id', $col = 'nombre',$where = null,$notFirstBlank=false, $order = null, $group = null, $count = null, $offset = null)
    {
        return $this->formSelect($label,$name, $key, $col,$where ,$notFirstBlank, $order, $group, $count, $offset, $idZona );
    }


    public function autocomplete($term, $col, $where = null)
    {


        $select = $this->select();
        $select->from($this->_name, array($col, 'c' => 'COUNT(*)'));

        if (!is_null($where))
        {
            $this->where($select, $where);
        }

        $select->where("$col LIKE ?", $term . '%');
        $select->orWhere("$col LIKE ?", '%' . $term . '%');
        $select->group($col);
        $select->order(array('c DESC', $col));
        $select->limit(8);

        $values = $this->getAdapter()->fetchCol($select);
        return $values;

    }


    public function _getCache()
    {
        if (null === $this->_cache)
        {
            $this->_cache = Zend_Controller_Front::getInstance()->getParam('bootstrap')->getResource('Cache');
        }
        return $this->_cache;
    }


    function _updateCache()
    {
        if ($this->_cache_activa)
        {
            $this->_cache = $this->_getCache();
            $this->_cache->remove($this->_name);
            $this->cache_assoc = $this->getAssoc();
            $this->_cache->save($this->cache_assoc, $this->_name);
        }
    }


    function cacheAssoc($id = null, $value = null, $where = null)
    {
        if ($this->_cache_activa)
        {

            $this->_cache = $this->_getCache();


            if (($this->cache_assoc = $this->_cache->load($this->_name)) === false)
            {
                $this->cache_assoc = $this->getAssoc();
                $this->_cache->save($this->cache_assoc, $this->_name);
            }
            
            
            if(!is_null($where))
            {
                
                foreach($where as $k => $v)
                {
                    $w=str_replace(array('=','>','<','>=','<=','!=','?'),array(' = ',' > ',' < ',' >= ',' <= ',' != ',$v),$k);
                    list($key_search,$exp,$value_search)=explode(' ',$w);

                    foreach($this->cache_assoc as $campo => $value)
                    {
                        switch($exp){
                            case '=':
                                if($value[$key_search] == $value_search) $this->cache_assoc2[$campo]=$value;
                                break;
                            case '>':
                                if($value[$key_search] > $value_search) $this->cache_assoc2[$campo]=$value;
                                break;
                            case '>=':
                                if($value[$key_search] >= $value_search) $this->cache_assoc2[$campo]=$value;
                                break;
                            case '<':
                                if($value[$key_search] < $value_search) $this->cache_assoc2[$campo]=$value;
                                break;
                            case '<=':
                                if($value[$key_search] <= $value_search) $this->cache_assoc2[$campo]=$value;
                                break;
                            default:
                                 $this->cache_assoc2[$campo]=$value;
                        }
                    }
                }
                 $this->cache_assoc=$this->cache_assoc2;
                
            }
            
           
           


            if (!is_null($id) and is_null($value))
                return $this->cache_assoc[$id];
            if (!is_null($id) and !is_null($value))
                return $this->cache_assoc[$id][$value];

            return $this->cache_assoc;

        } else
        {
            throw new Zend_Db_Table_Exception('Debe activar la cache, para poder usarla');
        }

    }


    function alter()
    {


        $info['cols'] = $this->getAdapter()->fetchCol("DESCRIBE ".$this->_name);


        try
        {
            if (!in_array('updated_on', $info['cols']))
            {
                $sqlAlter = "ALTER TABLE `$this->_name` ADD COLUMN `updated_on` DATETIME NULL";
                $this->getAdapter()->query($sqlAlter);
            }
            if (!in_array('created_on', $info['cols']))
            {
                $sqlAlter = "ALTER TABLE `$this->_name` ADD COLUMN `created_on` DATETIME NULL";
                $this->getAdapter()->query($sqlAlter);
            }
            if (!in_array('updated_by', $info['cols']))
            {
                $sqlAlter = "ALTER TABLE `$this->_name` ADD COLUMN `updated_by` INT NULL";
                $this->getAdapter()->query($sqlAlter);
            }
            if (!in_array('created_by', $info['cols']))
            {
                $sqlAlter = "ALTER TABLE `$this->_name` ADD COLUMN `created_by` INT NULL";
                $this->getAdapter()->query($sqlAlter);
            }

        }
        catch (exception $e)
        {

        }


    }

    function converToUtf8()
    {
        $select = $this->select();
        $rowset = $this->fetchAll($select);
        foreach ($rowset as $row)
        {
            foreach ($row->toArray() as $field => $value)
            {
                if (utf8_decode($value) != $value)
                {
                    $row->$field = utf8_decode($value);
                    $row->save();
                }
            }
        }
    }


    public function setDateRange(&$select, $get, $col)
    {
        if (empty($get))
            return true;

        $fechas = explode('-', $get);

        if (count($fechas) == 2)
        {
            $start = Sgit_Filter_DateTo::filter($fechas[0]);
            $end = Sgit_Filter_DateTo::filter($fechas[1]);
            $select->where("$col BETWEEN '$start' AND '$end'");
        } else
        {
            $fecha = Sgit_Filter_DateTo::filter($fechas[0]);
            $select->where("$col = ? ", $fecha);
        }
    }
    
    
    
    public function replace($keys,$forUpdate)
    {
        
        if (empty($forUpdate['updated_on']))
        {
            $forUpdate['updated_on'] = date('Y-m-d H:i:s');
        }

        if (empty($forUpdate['updated_by']))
        {
            $auth = Zend_Auth::getInstance();
            $forUpdate['updated_by'] = $auth->getIdentity()->id;
        }


        $record=array_merge($keys,$forUpdate);
        $updateKeys=array_keys($forUpdate);



        foreach($record as $v)
        {
            $ques[]='?';
        }
        
        $cols=implode(',',array_keys($record));
        $questions=implode(',',$ques);
        
        foreach($updateKeys as $v)
        {
            $forupdateValues[]=$record[$v];
            $forupdate[]=" $v = ? ";
        }

        $update=implode(',',$forupdate);
         
        
        $sql = "INSERT INTO {$this->_name} ($cols) VALUES ($questions)
          ON DUPLICATE KEY UPDATE $update";
     
        $values=array_merge(array_values($record), array_values($forupdateValues));


        $this->getAdapter()->query($sql, $values);
        
            
        
    }


}
